package main

import (
    "sort"
    "hash/crc32"
    "strconv"
)

type CHashNode struct {
    hash    uint32
    server  string
}

type CHashNodeList []CHashNode

func (l CHashNodeList) Len() int {
    return len(l)
}

func (l CHashNodeList) Less(i, j int) bool {
    return l[i].hash < l[j].hash
}

func (l CHashNodeList) Swap(i, j int) {
    l[i], l[j] = l[j], l[i]
}

type HashFunc func(data []byte) uint32

type CHashTable struct {
    hash    HashFunc
    repeat  int
    nodes   CHashNodeList
}

func newCHashTable() *CHashTable {
    ch := &CHashTable{}
    ch.repeat = 128
    ch.hash = crc32.ChecksumIEEE
    ch.nodes = make([]CHashNode, 0)
    
    return ch
}

func (ch *CHashTable) init(server []string) {
    for _, srv := range server {
        for i := 0; i < ch.repeat; i++ {
            node := srv + "#" + strconv.Itoa(i)
            hash := ch.hash([]byte(node))
            ch.nodes = append(ch.nodes, CHashNode{hash:hash, server:srv})
        }
    }
    
    sort.Sort(ch.nodes)
}

func (ch *CHashTable) get(str string) string {
    if len(ch.nodes) == 0 {
        return ""
    }
    
    hash := ch.hash([]byte(str))
    idx := sort.Search(len(ch.nodes), func(i int) bool { return ch.nodes[i].hash >= hash })
    if idx == len(ch.nodes) {
        idx = 0
    }
    
    debugLog.Println("client", str, "server", idx, ch.nodes[idx])
    return ch.nodes[idx].server
}